package com.whc.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
import com.whc.constant.JwtClaimsConstant;
import com.whc.constant.RedisHeader;
import com.whc.dto.UserLoginDto;
import com.whc.dto.UserRegisterDto;
import com.whc.entity.User;
import com.whc.properties.JwtProperties;
import com.whc.result.Result;
import com.whc.service.UserService;
import com.whc.utils.JwtUtil;
import com.whc.vo.FriendVo;
import com.whc.vo.SecurityUser;
import com.whc.vo.UserPageVo;
import com.whc.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;


import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 韦红材
 * @ClassName UserController
 * @data 2024/10/21 17:53
 * @Version V1.0
 **/
@RestController
@RequestMapping("/client/user")
@Api(tags = "用户模块")
@Slf4j
public class UserController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserService userService;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @ApiOperation("查询所有朋友")
    @GetMapping("/getAllFriends")
    @PreAuthorize("hasAuthority('user')")
    public Result<List<FriendVo>> getAllFriends(Long pid){
        List<FriendVo> friends=userService.getAllFriends(pid);

        return Result.success(friends);
    }

    @ApiOperation("修改用户状态")
    @GetMapping("/updateOnline")
    @PreAuthorize("hasAuthority('user')")
    public Result updateUserOnline(long id,long online){
        //在线
        if(online==1){
            //之前时不在线
            if(!redisTemplate.hasKey(RedisHeader.userOnline+id)){
                redisTemplate.opsForValue().set(RedisHeader.userOnline +id, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
            }
        }else{
            //之前在线
            if(redisTemplate.hasKey(RedisHeader.userOnline+id)){
                redisTemplate.delete(RedisHeader.userOnline+id);
            }
        }
        return Result.success();
    }

    @ApiOperation("查询用户状态")
    @GetMapping("/getOnline")
    @PreAuthorize("hasAuthority('user')")
    public Result<Integer> getUserOnline(long fid){
        if(redisTemplate.hasKey(RedisHeader.userOnline+fid)){
            return Result.success(1);
        }
        return Result.success(0);
    }

    @ApiOperation("获取验证码")
    @GetMapping("/getCode")
    public Result<Map<String, String>> getCode(){
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 50);
        String uuid = UUID.randomUUID().toString();
        //创建一个流，并把验证码输入到上面
        FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream();
        captcha.write(outputStream);
        String textCode=captcha.getCode();
        //设置一分钟的验证码缓存(不合实际)
//        redisTemplate.opsForValue().set(uuid,textCode, Duration.ofMinutes(1));
        redisTemplate.opsForValue().set(uuid,textCode);
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(5);
        map.put("uuid",uuid);
        map.put("textCode",textCode);
        map.put("img", Base64.encode(outputStream.toByteArray()));
        return Result.success(map);
    }


    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result<UserVo> login(@RequestBody UserLoginDto userLoginDto) {
        String uuid = userLoginDto.getUuid();
        String textCodeRedis = (String)redisTemplate.opsForValue().get(uuid);

        if(!userLoginDto.getTextCode().equalsIgnoreCase(textCodeRedis)){
            redisTemplate.delete(uuid);
            return Result.error("验证码错误");
        }
//        //删除redis里的验证码
        if(redisTemplate.hasKey(uuid)){
            redisTemplate.delete(uuid);
        }

        //先用security来验证
        try{
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(userLoginDto.getUsername(), userLoginDto.getPassword())
            );
            if(authentication==null){
                throw new RuntimeException("登录失败");
            }
            //把用户的认证信息，用id为键，存入redis
            UserDetails userDetails = (UserDetails)authentication.getPrincipal();

//            System.out.println("userDatils："+userDetails);
            User serviceUserByName = userService.getUserByName(userDetails.getUsername());
            //定义的一个对象模仿UserDetails的信息
            SecurityUser securityUser = new SecurityUser(
                    userDetails.getAuthorities(),userDetails.getPassword(),userDetails.getUsername(),
                    userDetails.isAccountNonExpired(),userDetails.isAccountNonLocked(),
                    userDetails.isCredentialsNonExpired(),userDetails.isEnabled()
            );

            redisTemplate.opsForValue().set(RedisHeader.userId+serviceUserByName.getId(),
                    securityUser);
            //拿到user,封装给vo对象，并且创建jwt，给到vo对象
            User user = userService.Login(userLoginDto);
            UserVo userVo=new UserVo();
            BeanUtils.copyProperties(user,userVo);
            //生成jwt
            HashMap<String,Object> map = new HashMap<>();
            map.put(JwtClaimsConstant.USER_ID,user.getId());
            String jwt = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), map);
            userVo.setToken(jwt);
            log.info("姓名"+userVo.getUsername()+"token:"+userVo.getToken());
            return Result.success(userVo);
        }catch (AuthenticationException e) {
            return Result.error("用户名或账号密码错误");
        }

    }


    @ApiOperation("退出登录")
    @PostMapping("/logout")
    @PreAuthorize("hasAuthority('user')")
    public Result<String> logout(){
        //只需把reids中的权限信息消除即可
        System.out.println("退出登录");
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
        SecurityUser userDetails = (SecurityUser)authentication.getPrincipal();
        User serviceUserByName = userService.getUserByName(userDetails.getUsername());

        redisTemplate.delete(RedisHeader.userId+serviceUserByName.getId());
        return Result.success("退出成功");
    }

    @ApiOperation("注册接口")
    @PostMapping("/register")
    public Result register(@RequestBody UserRegisterDto userRegisterDto){
        String uuid = userRegisterDto.getUuid();

        String textCodeRedis = (String)redisTemplate.opsForValue().get(uuid);
        if(!userRegisterDto.getTextCode().equalsIgnoreCase(textCodeRedis)){
            redisTemplate.delete(uuid);
            return Result.error("验证码错误");
        }
        //删除redis里的验证码
        redisTemplate.delete(uuid);

        userService.Register(userRegisterDto);
        return Result.success();
    }

    @ApiOperation("根据id查询用户")
    @GetMapping("/getUserById")

    public Result<UserPageVo> getUserById(Long userId){
        UserPageVo userPageVo=userService.getUserById(userId);
        return Result.success(userPageVo);
    }
//    public Result<UserVo> getUserById(Long userId){
//        UserVo userPageVo=userService.getUserVoById(userId);
//        return Result.success(userPageVo);
//    }

    @ApiOperation("根据id查询朋友")
    @GetMapping("/getFriendById")
    @PreAuthorize("hasAuthority('user')")
    public Result<FriendVo> getFriendById(Long userId){
        FriendVo friendVo=userService.getFriendById(userId);
        return Result.success(friendVo);
    }

    @ApiOperation("根据名称查询用户")
    @GetMapping("/getUserByName")
    @PreAuthorize("hasAuthority('user')")
    public Result<User> getUserByName(String userName){
        User user=userService.getUserByName(userName);
        System.out.println(user);
        return Result.success(user);
    }

    @ApiOperation("返回用户id接口")
    @GetMapping("/getUserId")
    @PreAuthorize("hasAuthority('user')")
    public Result<Long> getUsername(HttpSession session){
        long username =(long)session.getAttribute("userId");
        return Result.success(username);
    }


}
